﻿using System.Collections.Generic;
using System.Linq;
using System.Text;
using Asistente.Model.Representation;
using Asistente.Model.General;
using System;

namespace Asistente.Model.IFPUG
{
	// Esta clase correspnde con el modelo de ifpug resultante de la especificacion de el software a medir
	//por parte del medidor.

	//En el modelo se miden:
	
	//Casos de uso: Un caso de uso genera un TransformedUseCase, el cual es un objeto que tiene el caso 
	//de uso que es transformado, junto con la funcion transaccional generada.

	//Entidades: Una entidad genera una TrasformedEntity, el cual es un objeto que tiene la entidad 
	// transformada junto con la funcion de datos generada.

	//Controles:  Algunos controles generan funciones de trnasccion por lo tanto:
	//Un control  (que genera funcion de transaccion) genera un Transformed control, el cual es un objeto que 
	//tiene control que es transformado, junto con la funcion transaccional generada.

	public class IfpugModel : IMeasurable
	{
		public Application App {get; set;}
		public List<TransformedUseCase> TransformedUseCases { get; set; }
		public List<TransformedEntity> TransformedEntities { get; set; }
		public List<TransformedControl> TransformedControls{ get; set; }

		public IfpugModel() 
		{
			TransformedUseCases = new List<TransformedUseCase>();
			TransformedEntities = new List<TransformedEntity>();
			TransformedControls = new List<TransformedControl>();
		}

		public void Add(TransformedUseCase transformedUseCase) 
		{
			TransformedUseCases.Add(transformedUseCase);
		}

		public void Add(TransformedEntity transformedEntity) 
		{
			TransformedEntities.Add(transformedEntity);
		}

		public void Add(TransformedControl transformedControl)
		{
			TransformedControls.Add(transformedControl);
		}

		#region Medidas

		//La medicion de este modelo corresponde con medir cada uno de los elementos transformados.
		//Entidades (generan funciones de datos)
		//Casos de uso (generan funciones de transaccion)
		//Controles (algunos generan funciones de transaccion)

		public int Measure() 
		{            
			int ufp = 0;  

			//Se cuentan las funciones de tranasccion de los casos de uso    
			ufp += TransformedUseCases.Sum(transformedUc => transformedUc.Measure());

			//Se cuentan las funciones de tranasccion de los controles
			ufp += TransformedControls.Sum(transformedC => transformedC.Measure());

			//Se cuentn las funciones de datos           
			ufp += TransformedEntities.Sum(transformedE => transformedE.Measure());

			return ufp;
		}
		
		#endregion

		#region Print format 

		//Saluda del modelo  a HTML
		public string ToHtml()
		{
			StringBuilder content = new StringBuilder();

			content.AppendLine("<html>");

			//Resumen general
			content.AppendLine("<head>");
			content.AppendLine(GetSummary());
			content.AppendLine("</head>");

			content.AppendLine("<body>");
			content.AppendLine("<br>");
			content.AppendLine("<b><font size='3'>Trasactional functions</font></b>");
			content.AppendLine("<br>");
			content.AppendLine(GetTransactionalFunctionsHtmlTable());

			content.AppendLine("<br>");
			content.AppendLine("<b><font size='3'>Data functions</font></b>");
			content.AppendLine("<br>");
			content.AppendLine(GetDataFunctionsHtmlTable());

			content.AppendLine("</body>");
			content.AppendLine("</html>");

			return content.ToString();
		}

		private string GetSummary()
		{
			StringBuilder content = new StringBuilder();
			content.AppendLine("<b><font size='5' color='#0000A0'>IFPUG Summary</font></b>");
			content.AppendLine("<br>");
			content.AppendLine("<b><i><font size='4' color='#0000A0'> "+ App.Name + "</font></i></b>");
			content.AppendLine("<br>");
			content.AppendLine("<br>");
			content.AppendLine("Total size: " + Measure() + " UFP");
			content.AppendLine("<br>");
			content.AppendLine("Total time: " + App.GetTime());
			content.AppendLine("<br>");
			content.AppendLine("<br>");

			content.AppendLine("<i>Number of transacctional functions identified:</i> " + (TransformedUseCases.Count + TransformedControls.Count).ToString());
			content.AppendLine("<br>");
			content.AppendLine("<i>Number of data functions identified:</i> " + TransformedEntities.Count);
			content.AppendLine("<br>");

			return content.ToString();
		}

		//Salida del modelo en texto que se muestra en tab summaty
		public override string ToString()
		{
			StringBuilder content = new StringBuilder();

			content.AppendLine("Application name: " + App.Name);
			content.AppendLine("Total size: " + Measure() + " UFP");
			content.AppendLine("Total time: " + App.GetTime());
			content.AppendLine("\nHours: " + HoursMeasuring());
			content.AppendLine("Speed: " + Speed() + " UFP / Hour");

			content.AppendLine("\nNumber of transacctional functions identified: " + (TransformedUseCases.Count + TransformedControls.Count).ToString());
			content.AppendLine("Number of data functions identified: " + TransformedEntities.Count);

			//Se imprimen los transformed use cases
			content.AppendLine("\n\nTransactional functions");
			foreach (TransformedUseCase transformedUseCase in TransformedUseCases)
			{
				content.AppendLine(transformedUseCase.ToString());
			}

			//Se imprimen los transformed controls
			foreach (TransformedControl transformedControl in TransformedControls)
			{
				content.AppendLine(transformedControl.ToString());
			}

			content.AppendLine("\nQuantity: " + (TransformedUseCases.Count + +TransformedControls.Count).ToString());
			content.AppendLine("Total: " + (GetTotalTransformedUseCase() + GetTotalTransformedControls()).ToString());

			//Se imprimen las transformed entities
			content.AppendLine("\n\nData functions");
			foreach (TransformedEntity transformedEntity in TransformedEntities)
			{
				content.AppendLine(transformedEntity.ToString());
			}
			content.AppendLine("\nQuantity: " + TransformedEntities.Count);
			content.AppendLine("Total: " + GetTotalTransformedEntities());

			return content.ToString();
		}

		private string GetTransactionalFunctionsHtmlTable()
		{
			StringBuilder content = new StringBuilder();
			content.AppendLine("<table border='1' cellpadding='5' cellspacing='5'>");
			content.AppendLine("<tr><td>Name</td><td>Type</td><td>#DET</td><td>#FTR</td><td>UFP</td></tr>");

			//Se imprimen los transformed use cases
			foreach (TransformedUseCase transformedUseCase in TransformedUseCases)
			{
				content.Append("<tr>");
				content.Append(transformedUseCase.ToHtml());
				content.AppendLine("</tr>");
			}

			//Se imprimen los transformed controls
			foreach (TransformedControl transformedControl in TransformedControls)
			{
				content.Append("<tr>");
				content.Append(transformedControl.ToHtml());
				content.AppendLine("</tr>");
			}

			content.Append("<tr><td>Total</td><td></td><td></td><td>");
			content.Append((TransformedUseCases.Count  + TransformedControls.Count()).ToString());
			content.AppendLine("</td><td>" + (GetTotalTransformedUseCase() + GetTotalTransformedControls()).ToString() + "</td></tr>");
			content.AppendLine("</table>");
			return content.ToString();
		}

		private string GetDataFunctionsHtmlTable()
		{
			StringBuilder content = new StringBuilder();
			content.AppendLine("<table border='1' cellpadding='5' cellspacing='5'>");
			content.AppendLine("<tr><td>Name</td><td>Type</td><td>#DET</td><td>#RET</td><td>UFP</td></tr>");

			//Se imprimen las transformed entities
			foreach (TransformedEntity transformedEntity in TransformedEntities)
			{
				content.Append("<tr>");
				content.Append(transformedEntity.ToHtml());
				content.AppendLine("</tr>");
			}

			content.Append("<tr><td>Total</td><td></td><td></td><td>");
			content.Append(TransformedEntities.Count.ToString());
			content.AppendLine("</td><td>" + GetTotalTransformedEntities() + "</td></tr>");
			content.AppendLine("</table>");
			return content.ToString();
		}

		private object GetTotalTransformedEntities()
		{
			return TransformedEntities.Sum(transformedEntity => transformedEntity.Ufp);
		}

		private int GetTotalTransformedUseCase()
		{
			return TransformedUseCases.Sum(transformedUseCase => transformedUseCase.Ufp);
		}

		private int GetTotalTransformedControls()
		{
			return TransformedControls.Sum(transformedControl => transformedControl.Ufp);
		}


		private Double HoursMeasuring() 
		{
			Double minutesToHours = ((Double)App.Minutes / 60);
			Double secondToHours = ((Double)App.Seconds / 3600);
			Double hours = (Double)App.Hours;
			return hours + minutesToHours + secondToHours;
		}

		private Double Speed()
		{
			return (Double)Measure() / HoursMeasuring();
		}
		
		#endregion
	}
}
